<html>
<head>
<title>JavaScript file upload</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript">
if(!XMLHttpRequest.prototype.sendAsBinary){  
      XMLHttpRequest.prototype.sendAsBinary = function(datastr) {  
        function byteValue(x) {  
          return x.charCodeAt(0) & 0xff;  
        }  
        var ords = Array.prototype.map.call(datastr, byteValue);  
        var ui8a = new Uint8Array(ords);  
        this.send(ui8a.buffer);  
      };  
    }   
    
var Uploader = function(form) {
    this.form = form;
};

Uploader.prototype = {
    /**
     * @param Object HTTP headers to send to the server, the key is the
     * header name, the value is the header value
     */
    headers : {},
    imgdatas: {},
    mimetypes: {},

    /**
     * @return Array of DOMNode elements
     */
    get elements() {
        var fields = [];

        // gather INPUT elements
        var inputs = this.form.getElementsByTagName("INPUT");
        for (var l=inputs.length, i=0; i<l; i++) {
            fields.push(inputs[i]);
        }

        // gather SELECT elements
        var selects = this.form.getElementsByTagName("SELECT");
        for (var l=selects.length, i=0; i<l; i++) {
            fields.push(selects[i]);
        }

        return fields;
    },
    /**
     * @return String A random string
     */
    generateBoundary: function() {
        return "AJAX-----------------------" + (new Date).getTime();
    },

    /**
     * Constructs the message as discussed in the section about form
     * data transmission over HTTP
     *
     * @param Array elements
     * @param String boundary
     * @return String
     */
    buildMessage : function(elements, boundary, imgds) {
        var CRLF = "\r\n";
        var parts = [];

        elements.forEach(function(element, index, all) {
            var part = "";
            var type = "TEXT";

            if (element.nodeName.toUpperCase() === "INPUT") {
                type = element.getAttribute("type").toUpperCase();
            }

            if (type === "FILE" && element.files.length > 0) {
                var fieldName = element.name;
                var fileName = element.files[0].name;

                /*
                 * Content-Disposition header contains name of the field
                 * used to upload the file and also the name of the file as
                 * it was on the user's computer.
                 */
                part += 'Content-Disposition: form-data; ';
                part += 'name="' + fieldName + '"; ';
                part += 'filename="'+ fileName + '"' + CRLF;

                /*
                 * Content-Type header contains the mime-type of the file
                 * to send. Although we could build a map of mime-types
                 * that match certain file extensions, we'll take the easy
                 * approach and send a general binary header:
                 * application/octet-stream
                 */
                //part += "Content-Type: application/octet-stream";
                part += "Content-Type: image/png";
                
                part += CRLF + CRLF; // marks end of the headers part

                /*
                 * File contents read as binary data, obviously
                 */
                 var ddd = imgds[element.files[0].name];
                //var ui8a = new Uint8Array(ddd, 0);
                //for (var i = 0; i < text.length; i++) ui8a[i] = (text.charCodeAt(i) & 0xff);
                 //var bb = new BlobBuilder();
                 //bb.append(ddd);
                 var blob = new Blob( [ddd], // Data is a buffer!
                    {
                        type: 'application/octet-stream'
                    }
                );
                 
                part += ddd + CRLF;
                //part += element.files[0].getAsBinary() + CRLF;
           } else {
                /*
                 * In case of non-files fields, Content-Disposition
                 * contains only the name of the field holding the data.
                 */
                part += 'Content-Disposition: form-data; ';
                part += 'name="' + element.name + '"' + CRLF + CRLF;

                /*
                 * Field value
                 */
                part += element.value + CRLF;
           }

           parts.push(part);
        });

        var request = "--" + boundary + CRLF;
            request+= parts.join("--" + boundary + CRLF);
            request+= "--" + boundary + "--" + CRLF;

        return request;
    },
    /**
     * @return null
     */
    send : function() {
        var boundary = this.generateBoundary();
        var xhr = new XMLHttpRequest;

        xhr.open("POST", this.form.action, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                alert(xhr.responseText);
            }
        };
        var contentType = "multipart/form-data; boundary=" + boundary;
        xhr.setRequestHeader("Content-Type", contentType);

        for (var header in this.headers) {
            xhr.setRequestHeader(header, headers[header]);
        }

        // here's our data variable that we talked about earlier
        var data = this.buildMessage(this.elements, boundary, this.imgdatas);

        // finally send the request as binary data
        xhr.sendAsBinary(data);
    },
    send_base64: function(filename, data, mimetype) {
        var xhr = new XMLHttpRequest;
        xhr.open("POST", "/apis/upload/base64/"+filename, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                alert(xhr.responseText);
            }
        };
        xhr.setRequestHeader("Content-Type", mimetype+"; charset=utf-8");
        xhr.sendAsBinary(data);
    }
};
var readfile = function(file) {
    var reader1 = new FileReader();
    var reader2 = new FileReader();
    var reader3 = new FileReader();
    var reader4 = new FileReader();

    reader1.onload = reader2.onload = reader3.onload = reader4.onload = function (e) {
        //$('#blah').attr('src', e.target.result);
        console.log (e);
        console.log ("length", e.target.result.length);
        console.log (e.target.result);
    }

    reader1.readAsDataURL(file);
    //reader2.readAsArrayBuffer(file);
    //reader3.readAsText(file);
    //reader4.readAsBinaryString(file);
    
}

window.addEventListener("load", function() {
    var input = document.getElementById("photo");
    var img = document.getElementById("img");
    var previewBtn = document.getElementById("preview");

    var form = document.getElementsByTagName("form")[0];
    var uploader = new Uploader(form);
    var uploadBtn = document.getElementById("upload");

    previewBtn.addEventListener("click", function() {
        var reader1 = new FileReader();
        var reader2 = new FileReader();
        reader1.onload = function (e) {
            console.log (e);
            console.log ("length", e.target.result.length);
            console.log (e.target.result);
            img.src = e.target.result;
            uploader.imgdatas[input.files[0].name] = e.target.result;
        }
        reader2.onload = function (e) {
            uploader.imgdatas[input.files[0].name] = e.target.result;
        }
        reader1.readAsDataURL(input.files[0]);
        //reader2.readAsBinaryString(input.files[0]);
        //img.src = input.files[0].getAsDataURL();
        uploader.mimetypes[input.files[0].name] = input.files[0].type;
    }, false);

    uploadBtn.addEventListener("click", function() {
        //uploader.send();
        //uploader.send2(input.files[0]);
        var filename = input.files[0].name;
        uploader.send_base64(filename, uploader.imgdatas[filename], uploader.mimetypes[filename]);
    }, false);

}, false);

</script>
</head>
<body>


<form action="/apis/upload/form" method="post"
      enctype="multipart/form-data"
      onsubmit="return false;">
  <fieldset>
    <legend>Upload photo</legend>
    <label for="image_name">Image name:</label>
    <input type="text" name="image_name" id="image_name"> |
    <label for="image_type">Image type:</label>
    <select name="image_type" id="image_type">
      <option>JPEG</option>
      <option>PNG</option>
      <option>GIF</option>
    </select> |
    <input type="file" name="photo" id="photo">
    <input type="submit" value="Upload" id="upload">
    <input type="submit" value="Preview" id="preview">
    <hr>
    <img src="" alt="image preview" id="img">
  </fieldset>
</form>
</body>
</html>
